home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 301-325 / disk_319 / cnewssrc / cnews.orig.lzh / libcnews / string.c < prev    next >
C/C++ Source or Header  |  1989-06-27  |  6KB  |  257 lines

  1. /*
  2.  * string operations
  3.  */
  4.  
  5. #include <stdio.h>
  6. #include <ctype.h>
  7. #include <sys/types.h>
  8. #include "libc.h"
  9. #include "news.h"
  10.  
  11. /* forwards */
  12. char *findhost();
  13.  
  14. /*
  15.  * Return strsave() of the first word in "tokens".
  16.  * Words are delimited by spaces.
  17.  */
  18. char *
  19. first(tokens)
  20. char *tokens;
  21. {
  22.     return strsvto(tokens, ' ');
  23. }
  24.  
  25. /*
  26.  * Turn a newsgroup name into a file name, in place.
  27.  */
  28. void
  29. mkfilenm(ng)
  30. register char *ng;
  31. {
  32.     for (; *ng != '\0'; ng++)
  33.         if (*ng == NGDELIM)
  34.             *ng = FNDELIM;
  35. }
  36.  
  37. void
  38. trim(s)                    /* trim trailing newline */
  39. char *s;
  40. {
  41.     register char *nl;
  42.  
  43.     INDEX(s, '\n', nl);
  44.     if (nl != NULL)
  45.         *nl = '\0';
  46. }
  47.  
  48. char *
  49. skipsp(s)                /* skip any whitespace at *s */
  50. register char *s;
  51. {
  52.     while (iswhite(*s))
  53.         s++;
  54.     return s;
  55. }
  56.  
  57. char *
  58. strsvto(s, c)                /* save s up to (but excluding) c */
  59. char *s;
  60. int c;
  61. {
  62.     register char *endp, *copy;
  63.  
  64.     endp = index(s, c);        /* find interesting part's end of s */
  65.     if (endp != NULL)
  66.         *endp = '\0';        /* restored below */
  67.     copy = strsave(s);        /* copy interesting substring of s */
  68.         if (endp != NULL)
  69.             *endp = c;
  70.     return copy;
  71. }
  72.  
  73. int
  74. charcount(s, c)            /* how many c's in s? */
  75. register char *s;
  76. register int c;
  77. {
  78.     register int count = 0;
  79.  
  80. #ifdef CLASSY
  81.     for (; (s = index(s, c)) != NULL; s = (s == NULL? NULL: s+1))
  82.         ++count;
  83. #else
  84.     while (*s != '\0')
  85.         if (*s++ == c)
  86.             ++count;
  87. #endif                /* CLASSY */
  88.     return count;
  89. }
  90.  
  91. char *
  92. nullify(s)                /* return s or "" if NULL */
  93. register char *s;
  94. {
  95.     if (s == NULL)
  96.         return "";
  97.     else
  98.         return s;
  99. }
  100.  
  101. /*
  102.  * If c is NUL, hostchar will be false, so don't test (optimisation: ==).
  103.  */
  104. #define nothostchar(c, ch) (!hostchar(c, ch) /* || (c) == '\0' */ )
  105. /*
  106.  * True if c can be part of a hostname. RFC 850 allows letters, digits, periods
  107.  
  108.  * and hyphens and specifically disallows blanks. False may mean c is NUL.
  109.  */
  110. #define hostchar(c, ch) ((ch) = (c), \
  111.     (isascii(ch) && isalnum(ch) || (ch) == '.' || (ch) == '-'))
  112.  
  113. /*
  114.  * Return true iff any host in hosts appears in s, as per hostin().
  115.  * hosts are separated by non-hostname characters.
  116.  */
  117. boolean
  118. anyhostin(hosts, s)
  119. char *hosts, *s;
  120. {
  121.     register char *host = hosts;
  122.  
  123.     while (*host != '\0') {
  124.         register char *delimp;
  125.         register int ch;
  126.         register int delim;
  127.         register boolean hostisin;
  128.  
  129.         while (nothostchar(*host, ch) && *host != '\0')
  130.             ++host;            /* skip leading delims */
  131.         if (*host == '\0')        /* no more hosts */
  132.             break;
  133.         for (delimp = host; hostchar(*delimp, ch); delimp++)
  134.             ;            /* skip to next delim */
  135.         delim = *delimp;        /* may be NUL */
  136.         *delimp = '\0';            /* terminate host */
  137.         hostisin = hostin(host, s);
  138.         *delimp = delim;        /* restore hosts delimiter */
  139.         if (hostisin)
  140.             return YES;
  141.         host = delimp;            /* advance to next host */
  142.     }
  143.     return NO;
  144. }
  145.  
  146. /*
  147.  * Return true iff host appears in s, with no characters from the alphabet
  148.  * of legal hostname characters immediately adjacent.
  149.  */
  150. boolean
  151. hostin(host, s)
  152. register char *host, *s;
  153. {
  154.     return findhost(host, s) != NULL;
  155. }
  156.  
  157. /*
  158.  * Return the number of machines appearing in path,
  159.  * by counting transitions from delimiters.
  160.  * See hostin() for the rules, and the macros.
  161.  */
  162. int
  163. hopcount(path)
  164. register char *path;
  165. {
  166.     register int count = 0;
  167.     register int ch;
  168.  
  169.     for (; *path != '\0'; path++)
  170.         if (nothostchar(path[0], ch) && hostchar(path[1], ch))
  171.             ++count;    /* trailing edge of delimiters */
  172.     return count;
  173. }
  174.  
  175. char *
  176. sendersite(path)
  177. register char *path;
  178. {
  179.     register char *p;
  180.     register int ch;
  181.     static char *sender = NULL;
  182.  
  183.     nnfree(&sender);        /* free the last answer */
  184.     for (p = path; hostchar(*p, ch); p++)
  185.         ;
  186.     if (*p == '\0')            /* only a user name */
  187.         return hostname();    /* a local posting */
  188.     else {
  189.         register int delim = *p;
  190.  
  191.         *p = '\0';
  192.         sender = strsave(path);    /* copy the first machine name */
  193.         *p = delim;
  194.         return sender;
  195.     }
  196. }
  197.  
  198. /*
  199.  * Canonicalise rawpath: NULL -> "", chop last site (actually user name) but no
  200.  
  201.  * its leading delimiter, and if Approved:, chop everything after the site,
  202.  * and its trailing delimiter, from Approved: (or Sender:) (user@host).
  203.  * Result is malloced memory.
  204.  */
  205. char *
  206. canonpath(rawpath, approved, sender)
  207. char *rawpath, *approved, *sender;
  208. {
  209.     register char *newpath = strsave(nullify(rawpath));
  210.     register char *p, *lastdelim = newpath, *site = NULL;    /* p-csu v3 */
  211.     register int ch;
  212.  
  213.     for (p = newpath; *p != '\0'; ++p)
  214.         if (nothostchar(*p, ch))
  215.             lastdelim = p + 1;    /* just past delim; p-csu v3 */
  216.     if (lastdelim != NULL)
  217.         *lastdelim = '\0';        /* omit user's name */
  218.  
  219.     if (approved != NULL) {            /* moderated article */
  220.         site = index(approved, '@');
  221.         if (site == NULL)
  222.             site = index(nullify(sender), '@');
  223.     }
  224.     if (site != NULL) {
  225.         p = findhost(site+1, newpath);
  226.         if (p != NULL && *p++ != '\0')    /* delim after site? p-csu v3 */
  227.             *p = '\0';        /* terminate newpath after site */
  228.     }
  229.     return newpath;
  230. }
  231.  
  232. /*
  233.  * Return pointer to the first byte after host in path, if any,
  234.  * with no characters from the alphabet of legal hostname characters
  235.  * immediately adjacent.
  236.  * This function is a profiling hot spot, so it has been optimised.
  237.  */
  238. char *
  239. findhost(host, path)
  240. register char *host, *path;
  241. {
  242.     register int hostlen = strlen(host), ch;
  243.  
  244.     /* Special case: match host!path or host. */
  245.     if (STREQN(path, host, hostlen) && nothostchar(path[hostlen], ch))
  246.         return &path[hostlen];
  247.  
  248.     /* Match path2!host!path or path2!host. */
  249.     while (*path != '\0')
  250.         if (hostchar(path[0], ch))    /* can't start after here */
  251.             ++path;
  252.         else if ((++path, STREQN(path, host, hostlen)) &&
  253.                nothostchar(path[hostlen], ch))
  254.             return &path[hostlen];
  255.     return NULL;
  256. }
  257.